package com.nx.platform.entry.utility;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import com.nx.arch.nxrpc.client.proxy.builder.ProxyFactory;
import com.nx.platform.entry.service.RpcHelper;
import com.nx.platform.openentry.contract.ICmdRouterService;
import com.nx.platform.openentry.entity.response.OpenEntryCmdDto;
import com.nx.platform.openentry.entity.response.OpenEntryModuleDTO;

import lombok.extern.slf4j.Slf4j;

/**
 * @author alex
 * @brief
 * @date 2019/12/2
 */
@Slf4j
public class EntryConfigHelper {

    //缓存统一服务远程调用对象
    private static final Map<String, ICmdRouterService> ROUTER_SERVICE_CACHE = new HashMap<>();

    //缓存cmd到服务的配置
    private static final Map<String, Map<String, OpenEntryCmdDto>> CMD_CONFIG_CACHE = new HashMap<>();

    //缓存module调用信息
    private static final Map<String, OpenEntryModuleDTO> ROUTER_SERVICE_MAP = new HashMap<>();

    //moduleId 进程内缓存
    public static final Map<Long, OpenEntryModuleDTO> MODULE_ID_MAP = new HashMap<>();

    public static void init(){

        log.info("ScfServiceCache load config start...");
        reloadRouterServiceCache();
        reloadCmdConfigCache();
        log.info("ScfServiceCache load config end...");

        SimpleDateFormat sdf = new SimpleDateFormat("ss");
        int initialDelay = 60 - Integer.parseInt(sdf.format(new Date()));

        // 每30秒刷新
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                log.info("ScfServiceCache reload config start...");
                reloadRouterServiceCache();
                reloadCmdConfigCache();
                log.info("ScfServiceCache reload config end...");
            }
        }, initialDelay, 30, TimeUnit.SECONDS);

    }

    private static void reloadRouterServiceCache(){
        try {
            List<OpenEntryModuleDTO> configList = RpcHelper.openEntryConfService.getAllModuleConfigure("entry_load_module_config");
            if (!CollectionUtils.isEmpty(configList)) {
                configList.forEach(x -> MODULE_ID_MAP.put(x.getId(), x));
                for (OpenEntryModuleDTO config : configList) {
                    String moduleName = config.getModuleName();
                    String modulePath = config.getModulePath();
                    OpenEntryModuleDTO moduleConfig = ROUTER_SERVICE_MAP.get(moduleName);
                    ICmdRouterService routerService = ROUTER_SERVICE_CACHE.get(modulePath);
                    if (routerService == null || moduleConfig == null || !moduleConfig.getModuleServiceName().equals(config.getModuleServiceName())) {
                        String implName = "DefaultRouterService";
                        if (StringUtils.isNotEmpty(config.getModuleServiceName())) {
                            String[] implPath = config.getModuleServiceName().split("\\.");
                            implName = implPath[implPath.length - 1];
                        }
                        routerService = ProxyFactory.create(ICmdRouterService.class, "tcp://" + moduleName + "/" + implName);
                        ROUTER_SERVICE_MAP.put(moduleName, config);
                    }

                    // modulepath 已更改
                    if (moduleConfig != null && !moduleConfig.getModulePath().equals(config.getModulePath())) {
                        ROUTER_SERVICE_CACHE.remove(moduleConfig.getModulePath());
                        log.info("ScfServiceCache reloadRouterServiceCache remove service cache . modulepath = "
                                + moduleConfig.getModulePath() + " modulename = " + moduleConfig.getModuleName());
                    }
                    ROUTER_SERVICE_CACHE.put(modulePath, routerService);
                    log.info("ScfServiceCache reloadRouterServiceCache loading module config. modulepath = " + modulePath + " modulename = " + moduleName);
                }
            }
        } catch (Exception e){
            log.error("ScfServiceCache reloadRouterServiceCache error " + E2s.exception2String(e));
        }
    }

    private static void reloadCmdConfigCache(){
        try {
            List<OpenEntryCmdDto> configList = RpcHelper.openEntryConfService.getAllCommandConfigure("entry_load_method_config");
            if (!CollectionUtils.isEmpty(configList)){
                Map<String, OpenEntryCmdDto> commandMap;
                for (OpenEntryCmdDto config : configList){
                    commandMap = CMD_CONFIG_CACHE.computeIfAbsent(MODULE_ID_MAP.get(config.getModuleId()).getModulePath(), k -> new HashMap<String, OpenEntryCmdDto>());
                    commandMap.put(config.getCommandName(), config);
                    log.info("ScfServiceCache reloadCmdConfigCache loading command config. modulepath = " + MODULE_ID_MAP.get(config.getModuleId()).getModulePath() + " commandname = " + config.getCommandName() + " methodSign=" + config.getMethodSign());
                }

            }
        } catch (Exception e){
            log.error("ScfServiceCache reloadCmdConfigCache error ", e);
        }

    }

    public static ICmdRouterService getService(String modulePath){
        return ROUTER_SERVICE_CACHE.get(modulePath);
    }

    public static OpenEntryCmdDto getCommandConfig(String modulePath, String command){
        Map<String, OpenEntryCmdDto> commandConfigMap = CMD_CONFIG_CACHE.get(modulePath);
        if (!CollectionUtils.isEmpty(commandConfigMap)){
            return commandConfigMap.get(command);
        }
        return null;
    }
}
